package org.dromara.common.excel.convert

import cn.hutool.core.annotation.AnnotationUtil
import cn.hutool.core.convert.Convert
import cn.idev.excel.converters.Converter
import cn.idev.excel.enums.CellDataTypeEnum
import cn.idev.excel.metadata.GlobalConfiguration
import cn.idev.excel.metadata.data.ReadCellData
import cn.idev.excel.metadata.data.WriteCellData
import cn.idev.excel.metadata.property.ExcelContentProperty
import io.github.oshai.kotlinlogging.KotlinLogging
import org.dromara.common.core.service.DictService
import org.dromara.common.core.utils.SpringUtils.getBean
import org.dromara.common.core.utils.StringUtils
import org.dromara.common.excel.annotation.ExcelDictFormat
import org.dromara.common.excel.utils.ExcelUtil.convertByExp
import org.dromara.common.excel.utils.ExcelUtil.reverseByExp
import java.lang.reflect.Field

/**
 * 字典格式化转换处理
 *
 * @author Lion Li
 * @updater LikeYouDo
 * @date 2025/1/14 15:37
 */
open class ExcelDictConvert : Converter<Any> {
    companion object {
        private val log = KotlinLogging.logger { }
    }

    override fun supportJavaTypeKey(): Class<Any> {
        return Any::class.java
    }

    override fun supportExcelTypeKey(): CellDataTypeEnum? {
        return null
    }

    override fun convertToJavaData(
        cellData: ReadCellData<*>,
        contentProperty: ExcelContentProperty,
        globalConfiguration: GlobalConfiguration?
    ): Any {
        val anno = getAnnotation(contentProperty.field)
        val type = anno.dictType
        val label = cellData.stringValue
        val value = if (StringUtils.isBlank(type)) {
            reverseByExp(label, anno.readConverterExp, anno.separator)
        } else {
            getBean(DictService::class.java).getDictValue(type, label, anno.separator)
        }
        return Convert.convert(contentProperty.field.type, value)
    }

    override fun convertToExcelData(
        obj: Any?,
        contentProperty: ExcelContentProperty,
        globalConfiguration: GlobalConfiguration?
    ): WriteCellData<String> {
        if (obj == null) {
            return WriteCellData("")
        }
        val anno = getAnnotation(contentProperty.field)
        val type = anno.dictType
        val value = Convert.toStr(obj)
        val label = if (StringUtils.isBlank(type)) {
            convertByExp(value, anno.readConverterExp, anno.separator)
        } else {
            getBean(DictService::class.java).getDictLabel(type, value, anno.separator)
        }
        return WriteCellData(label)
    }

    private fun getAnnotation(field: Field): ExcelDictFormat {
        return AnnotationUtil.getAnnotation(field, ExcelDictFormat::class.java)
    }
}
